#include <bits/stdc++.h>

#define MAX_THREADS 4
#define START 100
#define END 400

using namespace std;

atomic<int> prime_count(0); // 统计素数的数量
mutex cnt_mut; // 保护prime_count的互斥锁

// 待判断的数字，0表示待发放任务，-1表示所有任务结束，大于0表示具体执行的任务
atomic<int> job_num(0);
mutex job_mut; // 保护job_num的互斥锁
condition_variable job_cond; // 条件变量

bool is_prime(int num);
static void thr_job(void);

int main(void)
{
	vector<thread> threads;
	int i;

	// 创建线程
	for (i = 0; i < MAX_THREADS; i++)
		threads.push_back(thread(thr_job));

	// 发放任务
	for (i = START; i <= END; i++) {
		unique_lock<mutex> lock(job_mut);

		// 如果job_num大于0，说明有线程在执行任务，条件变量等待
		while (job_num > 0)
			job_cond.wait(lock); // 等待线程执行完任务

		job_num = i; // 发放任务
		job_cond.notify_one(); // 通知一个线程

		lock.unlock();
	}

	// 结束所有线程

	unique_lock<mutex> lock(job_mut);
	job_num = -1; // 结束所有线程
	job_cond.notify_all(); // 通知所有线程
	lock.unlock();


	// 等待所有线程结束
	for (auto &t : threads) {
		if (t.joinable()) // joinable()函数判断线程是否可以连接
			t.join();
	}

	// 输出结果
	cout << "质数的数量: " << prime_count << endl;

	return 0;
}


bool is_prime(int num)
{
	int i;
	if (num < 2)
		return false;

	for (i = 2; i <= num / i; i++) {
		if (num % i == 0)
			return 0;
	}

	return true;
}

static void thr_job(void)
{
	while (true) {
		unique_lock<mutex> lock(job_mut);

		// 等待任务
		while (job_num == 0) {
			// 如果job_num等于0，说明主线程没有发布任务，条件变量等待
			job_cond.wait(lock);
		}

		if (job_num == -1) { // 结束所有线程
			lock.unlock();
			break;
		}

		int num = job_num; // 获取任务
		job_num = 0; // 清空任务
		// 唤醒其他线程，主要是唤醒主线程分配任务
		job_cond.notify_all();
		// 释放锁
		lock.unlock();

		// 执行任务
		if (is_prime(num)) {
			// 统计素数的数量
			cnt_mut.lock();
			cout << num << " 是质数" << endl;
			prime_count++;
			cnt_mut.unlock();
		}
	}
}
